/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GameController;

import Car.Car;
import GameView.RCCanvas;
import Point.Point;
import java.util.Random;
import java.util.Vector;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.MIDlet;

/**
 * Controller dari game
 * @author Christianto
 */
public class RCController 
        extends MIDlet
        implements CommandListener {
    
    private Random generator = new Random(2032L);
    private boolean started = false;
    private int MaxSpeed = 30;
    private int MaxLane = 10;
    private int rentang = 20;
    private int MaxCar = 128;
    private Vector ExistedCars;
    private Canvas RCView;
    private Display dsp;
    
    private Command CExit  = new Command("Exit", Command.EXIT, 5);
    
    public RCController()  {
        
        //System.out.println("DEBUGRCController started");

        ExistedCars = new Vector(10);
        
        //System.out.println("DEBUGSize: "+ExistedCars.size());
        
        //System.out.println("DEBUGadding Car#1");
        Point StartPos = new Point(0,0);//line , posy
        Car tempcar = new Car(StartPos,6);
        ExistedCars.addElement(tempcar);
        
        //System.out.println("DEBUGadding Car#2");
        StartPos = new Point(1,-4);
        tempcar = new Car(StartPos,15);
        ExistedCars.addElement(tempcar);

        //System.out.println("DEBUGadding Car#3");
        StartPos = new Point(2,8);
        tempcar = new Car(StartPos,7);
        ExistedCars.addElement(tempcar);
        
        //System.out.println("DEBUGadding Car#4");
        StartPos = new Point(3,4);
        tempcar = new Car(StartPos,13);
        ExistedCars.addElement(tempcar);

        //System.out.println("DEBUGadding Car#5");
        StartPos = new Point(4,4);
        tempcar = new Car(StartPos,10);
        ExistedCars.addElement(tempcar);
        
        //System.out.println("DEBUGadding Car#6");
        StartPos = new Point(5,2);
        tempcar = new Car(StartPos,27);
        ExistedCars.addElement(tempcar);
        
        //System.out.println("DEBUGadding Car#7");
        StartPos = new Point(6,3);
        tempcar = new Car(StartPos,8);
        ExistedCars.addElement(tempcar);
        
        //System.out.println("DEBUGadding Car#8");
        StartPos = new Point(7,-12);
        tempcar = new Car(StartPos,20);
        ExistedCars.addElement(tempcar);
        
        //System.out.println("DEBUGadding Car#9");
        StartPos = new Point(8,-32);
        tempcar = new Car(StartPos,30);
        ExistedCars.addElement(tempcar);
        
        RCView = new RCCanvas(ExistedCars);
        RCView.addCommand(CExit);
        RCView.setCommandListener(this);
        dsp = Display.getDisplay(this);
        dsp.setCurrent(RCView);
        
        //System.out.println("DEBUGSize: "+ExistedCars.size());
    }
    
    public void startApp() {
        if (!started) {
            while(ExistedCars.size() > 0){
                //System.out.println("DEBUGUpdating..");
                for (int i=0;i<ExistedCars.size();++i) {
                    Car x = (Car)ExistedCars.elementAt(i);
                    x.Update(rentang);
                    if ((generator.nextInt(100) <= 20) && (MaxSpeed-(int)x.getVel() > 0)) {
                        x.SetVel((1+x.getVel()<30)?1+x.getVel():20);
                    }                    
                    //System.out.println("DEBUGUpdated: "+x);
                    ExistedCars.setElementAt(x, i);
                    if (x.getPos().getOrdinat()>22){
                        //System.out.println("DEBUGRemove OutofBounds : "+i);
                        ExistedCars.removeElementAt(i);
                    }
                }
                
                int check = generator.nextInt(100);
                if (ExistedCars.size() <= MaxCar && check <= 55) {
                    AddCar();
                } 
                //Check whether there are collisions.
                CollisionChecker();
                
                // Update Display
                RCView = new RCCanvas(ExistedCars);
                RCView.addCommand(CExit);
                RCView.setCommandListener(this);
                dsp = Display.getDisplay(this);
                dsp.setCurrent(RCView);      
        
                long t0,t1;
                t0=System.currentTimeMillis();
                do{
                    t1=System.currentTimeMillis();
                }
                while (t1-t0<100);
            }
            notifyDestroyed();
        } else {
        }
    }
    
    public void pauseApp() {
    }
    
    public void destroyApp(boolean unconditional) {
    }

    public void commandAction(Command c, Displayable d) {
        if (c==CExit){
            System.out.println("DEBUG : EXIT");
            ExistedCars.removeAllElements();
            destroyApp(false);
            notifyDestroyed();
        }
    }
    
    /**
     * Procedure to checked if any of the cars are colliding
     * right now.
     * Delete (destroy) them whenever necessary.
     */
    private void CollisionChecker() {   
        boolean hapus[] = new boolean[ExistedCars.size()];
        for (int i = 0;i<ExistedCars.size();++i) hapus[i] = false;

        for (int i=0;i<ExistedCars.size();++i) {
            for (int j=0;j<i;++j) {
                Point c1 = ((Car)ExistedCars.elementAt(i)).getPos();
                Point c2 = ((Car)ExistedCars.elementAt(j)).getPos();
                hapus[i] = hapus[i] || collide(c1,c2);
                hapus[j] = hapus[j] || collide(c1,c2);
                
                if (collide(c1,c2)) System.out.println(c1 + " -> " + c2);
            }
        }

        Vector survivor = new Vector();
        for (int i=0;i<ExistedCars.size();++i) {
            if (!hapus[i]) {
                survivor.addElement(ExistedCars.elementAt(i));
                //System.out.println("DEBUGHapus "+i);
            }
        }
        ExistedCars = survivor;
    }
    
    private boolean collide(Point a, Point b) {
        double akiri = Math.floor(a.getAbsis())-0.4;
        double abawah = Math.floor(a.getOrdinat());
        
        double bkiri = Math.floor(b.getAbsis())-0.4;
        double bbawah = Math.floor(b.getOrdinat());
        
        return (Math.max(akiri, bkiri)<=Math.min(akiri, bkiri)+0.8)&&
               (Math.max(abawah, bbawah)<=Math.min(abawah,bbawah)+1.0);
    }
    
    /**
     * Procedure to add a new car to the screen.
     * Either add at the top or the bottom of the screen.
     */
    private void AddCar() {
        ExistedCars.addElement(new Car(new Point(generator.nextInt(MaxLane-1),-5),
                generator.nextInt(MaxSpeed-1)+1));
    }
}
